<!-- HTMX Form Field Partial -->
<!-- Renders a single form field with HTMX enhancements -->
{% set field_id = field.id or field.name %}
{% set field_name = field.name %}
{% set field_value = field.value if field.value is defined else '' %}
{% set field_type = field.type|lower %}
{% set col_class = field.col_class|default('col-md-6') %}
{% set custom_component = field.custom_component|default('') %}
{% set uses_custom_label = custom_component == 'merge_environment_toggle' %}
{% set is_toggle_field = field_type in ['checkbox', 'toggle'] %}
{% set is_deepspeed_field = field_name == 'deepspeed_config' or field_id == 'deepspeed_config' %}

<div class="{{ col_class }} mb-3 {{ field.extra_classes|default('') }}"
     x-on:input="$store.trainer.markFormDirty()"
     x-on:change="$store.trainer.markFormDirty()"
     data-field-name="{{ field.name }}"
     {% if field.conditional_on %}
     data-conditional-on="{{ field.conditional_on }}"
     {% endif %}>

    <!-- Field Label -->
    {% if not uses_custom_label %}
    {% if is_deepspeed_field %}
    <div class="d-flex align-items-center justify-content-between gap-2">
    {% endif %}
        <label id="{{ field_id }}__title"
               {% if not is_toggle_field %}for="{{ field_id }}"{% endif %}
               class="form-label{% if is_deepspeed_field %} mb-0{% endif %}">
            {{ field.label }}
            {% if field.required %}
            <span class="text-danger">*</span>
            {% endif %}

            <!-- Help Icon with Tooltip -->
            {% if field.description or field.cmd_args_help %}
            <i class="fas fa-question-circle text-muted ms-1"
               data-bs-toggle="tooltip"
               data-bs-placement="top"
               title="{{ field.cmd_args_help|default(field.description) }}"></i>
            {% endif %}
        </label>
        {% if is_deepspeed_field %}
            <button type="button"
                    class="deepspeed-launch-btn"
                    data-target-field="{{ field_id }}"
                    onclick="if (window.launchDeepSpeedBuilderButton) { window.launchDeepSpeedBuilderButton(this); } else if (window.openDeepSpeedBuilderFromButton) { window.openDeepSpeedBuilderFromButton(this); } else { console.warn('DeepSpeed builder not loaded'); }">
                <span class="btn-icon">🧙</span> DeepSpeed Builder
            </button>
        </div>
        {% endif %}
    {% endif %}

    <!-- Field Input based on type -->
    {% if custom_component == 'dataset_config_select' %}
        <div class="dataset-dropdown dropdown w-100"
             data-field-id="{{ field_id }}"
             data-selected-env="{{ field.selected_environment or '' }}"
             data-selected-path="{{ field.selected_path or '' }}">
            <input type="hidden"
                   id="{{ field_id }}"
                   name="{{ field_name }}"
                   value="{{ field_value }}"
                   {% if field.required %}data-required="true"{% endif %}>

            <button class="btn btn-outline-secondary w-100 dropdown-toggle dataset-toggle"
                    type="button"
                    data-bs-toggle="dropdown"
                    aria-expanded="false">
                <span class="dataset-toggle-label d-flex justify-content-between align-items-center">
                    {% if field.selected_path %}
                        <span class="dataset-env">{{ field.selected_environment }}</span>
                        <span class="dataset-path">{{ field.selected_path }}</span>
                    {% else %}
                        <span class="text-muted">Select dataset configuration</span>
                    {% endif %}
                </span>
            </button>

            <div class="dropdown-menu w-100 dataset-dropdown-menu">
                {% for option in field.options %}
                    <button class="dropdown-item dataset-option"
                            type="button"
                            data-value="{{ option.value }}"
                            data-environment="{{ option.environment }}"
                            data-path="{{ option.path }}">
                        <span class="d-flex justify-content-between align-items-center w-100">
                            <span class="dataset-env">{{ option.environment }}</span>
                            <span class="dataset-path">{{ option.path }}</span>
                        </span>
                    </button>
                {% endfor %}
            </div>
        </div>

        <script>
            (function() {
                if (!window.__datasetDropdownInit) {
                    window.__datasetDropdownInit = true;

                    const updateDropdownLabel = function(dropdown, value) {
                        if (!dropdown) return;
                        const toggle = dropdown.querySelector('.dataset-toggle-label');
                        if (!toggle) return;

                        const hiddenInput = dropdown.querySelector('input[type="hidden"]');
                        const fallbackValue = value != null ? value : hiddenInput ? hiddenInput.value : '';

                        const env = dropdown.dataset.selectedEnv || dropdown.dataset.defaultEnv || '';
                        const path = dropdown.dataset.selectedPath || dropdown.dataset.defaultPath || '';

                        if (env && path) {
                            toggle.innerHTML = `
                                <span class="dataset-env">${env}</span>
                                <span class="dataset-path">${path}</span>
                            `;
                        } else if (path) {
                            toggle.innerHTML = `
                                <span class="dataset-path">${path}</span>
                            `;
                        } else if (fallbackValue) {
                            toggle.textContent = fallbackValue;
                        } else {
                            toggle.innerHTML = '<span class="text-muted">Select dataset configuration</span>';
                        }
                    };

                    const syncDropdownDefaults = function(dropdown, env, path) {
                        if (!dropdown) return;
                        if (env && !dropdown.dataset.defaultEnv) {
                            dropdown.dataset.defaultEnv = env;
                        }
                        if (path && !dropdown.dataset.defaultPath) {
                            dropdown.dataset.defaultPath = path;
                        }
                    };

                    const applySelection = function(dropdown, env, path, value, triggerChange) {
                        if (!dropdown) return;
                        const hiddenInput = dropdown.querySelector('input[type="hidden"]');
                        if (hiddenInput && typeof value === 'string') {
                            const previousValue = hiddenInput.value;
                            hiddenInput.value = value;
                            if (triggerChange && previousValue !== value) {
                                hiddenInput.dispatchEvent(new Event('change', { bubbles: true }));
                            }
                        }

                        if (env && path) {
                            dropdown.dataset.selectedEnv = env;
                            dropdown.dataset.selectedPath = path;
                        }
                        syncDropdownDefaults(dropdown, env, path);

                        const targetValue = value != null ? value : hiddenInput ? hiddenInput.value : '';
                        if (targetValue) {
                            dropdown.dataset.lastValue = targetValue;
                        }
                        dropdown.querySelectorAll('.dataset-option').forEach(function(item) {
                            const itemValue = item.dataset.value || '';
                            if (itemValue === targetValue) {
                                item.classList.add('active');
                            } else {
                                item.classList.remove('active');
                            }
                        });

                        updateDropdownLabel(dropdown, value);
                    };

                    window.__setDatasetSelection = applySelection;

                    window.__refreshDatasetDropdowns = function() {
                        document.querySelectorAll('.dataset-dropdown').forEach(function(dropdown) {
                            const hiddenInput = dropdown.querySelector('input[type="hidden"]');
                            if (!hiddenInput) return;
                            const currentValue = hiddenInput.value;
                            const storedValue = dropdown.dataset.lastValue || '';
                            const valueToApply = currentValue || storedValue;
                            const env = dropdown.dataset.selectedEnv || dropdown.dataset.defaultEnv || '';
                            const path = dropdown.dataset.selectedPath || dropdown.dataset.defaultPath || '';
                            applySelection(dropdown, env, path, valueToApply, false);
                        });
                    };

                    document.addEventListener('htmx:afterSwap', function() {
                        window.__refreshDatasetDropdowns();
                    });

                    document.addEventListener('htmx:afterSettle', function() {
                        window.__refreshDatasetDropdowns();
                    });

                    document.addEventListener('click', function(event) {
                        const optionEl = event.target.closest('.dataset-option');
                        if (!optionEl) {
                            return;
                        }

                        const dropdown = optionEl.closest('.dataset-dropdown');
                        if (!dropdown) {
                            return;
                        }

                        const env = optionEl.dataset.environment || '';
                        const path = optionEl.dataset.path || '';
                        const value = optionEl.dataset.value || '';

                        applySelection(dropdown, env, path, value, true);

                        const toggleButton = dropdown.querySelector('.dataset-toggle');
                        if (toggleButton && window.bootstrap && window.bootstrap.Dropdown) {
                            try {
                                const instance = window.bootstrap.Dropdown.getInstance(toggleButton) || new window.bootstrap.Dropdown(toggleButton);
                                instance.hide();
                            } catch (err) {
                                console.debug('dataset dropdown hide failed', err);
                            }
                        }
                    });

                    document.querySelectorAll('.dataset-dropdown').forEach(function(dropdown) {
                        const hiddenInput = dropdown.querySelector('input[type="hidden"]');
                        if (hiddenInput && !hiddenInput.dataset.datasetObserver) {
                            const observer = new MutationObserver(function() {
                                updateDropdownLabel(dropdown, hiddenInput.value);
                            });
                            observer.observe(hiddenInput, { attributes: true, attributeFilter: ['value'] });
                            hiddenInput.dataset.datasetObserver = 'true';
                        }
                    });
                }

                document.querySelectorAll('.dataset-dropdown').forEach(function(dropdown) {
                    const hiddenInput = dropdown.querySelector('input[type="hidden"]');
                    const currentValue = hiddenInput ? hiddenInput.value : '';
                    const optionEl = currentValue
                        ? dropdown.querySelector(`.dataset-option[data-value="${CSS.escape(currentValue)}"]`)
                        : null;
                    const initialEnv = optionEl ? optionEl.dataset.environment : dropdown.dataset.selectedEnv || '';
                    const initialPath = optionEl ? optionEl.dataset.path : dropdown.dataset.selectedPath || '';
                    if (currentValue) {
                        dropdown.dataset.lastValue = currentValue;
                    }
                    if (!dropdown.dataset.defaultEnv && initialEnv && initialPath) {
                        dropdown.dataset.defaultEnv = initialEnv;
                        dropdown.dataset.defaultPath = initialPath;
                    }
                    const valueToApply = currentValue || dropdown.dataset.lastValue || '';
                    window.__setDatasetSelection(dropdown, initialEnv, initialPath, valueToApply, false);
                });
            })();
        </script>

    {% elif custom_component == 'prompt_library_path' %}
        <div class="prompt-library-selector" data-prompt-library-field="{{ field_id }}">
            <div class="input-group">
                <div class="prompt-library-dropdown dropdown flex-grow-1">
                    <input type="hidden"
                           id="{{ field_id }}"
                           name="{{ field_name }}"
                           value="{{ field_value }}"
                           {% if field.required %}data-required="true"{% endif %}
                           {% if field.disabled %}disabled{% endif %}
                           data-debounce="500"
                           hx-post="/api/validate/{{ field_id }}"
                           hx-trigger="change"
                           hx-target="#field-feedback-{{ field_id }}"
                           hx-swap="innerHTML"
                           hx-on::after-request="window.handleFieldValidation(event, this)"
                           data-feedback-id="field-feedback-{{ field_id }}">
                    <button class="btn btn-outline-secondary w-100 dropdown-toggle prompt-library-toggle"
                            type="button"
                            data-bs-toggle="dropdown"
                            aria-expanded="false"
                            {% if field.disabled %}disabled{% endif %}>
                        <span class="prompt-library-toggle-label">
                            {% if field_value %}
                                <span class="prompt-library-toggle-name">Custom path</span>
                                <span class="prompt-library-toggle-path">{{ field_value }}</span>
                            {% else %}
                                <span class="text-muted">Select prompt library</span>
                            {% endif %}
                        </span>
                    </button>
                    <div class="dropdown-menu w-100 prompt-library-menu" role="menu"></div>
                </div>
                <button class="btn btn-outline-secondary"
                        type="button"
                        id="prompt-library-button-{{ field_id }}"
                        data-prompt-library-trigger
                        data-prompt-library-target="{{ field_id }}">
                    <i class="fas fa-book"></i>
                    <span data-prompt-library-button-label>
                        {{ 'Edit prompt library' if field_value else 'Create prompt library' }}
                    </span>
                </button>
            </div>
            <div class="d-flex justify-content-between align-items-center mt-2">
                <button type="button"
                        class="btn btn-link btn-sm px-0 prompt-library-custom-toggle"
                        data-custom-toggle="{{ field_id }}"
                        {% if field.disabled %}disabled{% endif %}>
                    Use custom path
                </button>
                <small class="text-muted">Libraries live under validation_prompt_libraries/</small>
            </div>
            <div class="prompt-library-custom d-none mt-2" data-custom-container="{{ field_id }}">
                <input type="text"
                       class="form-control form-control-sm"
                       placeholder="{{ field.placeholder|default('/path/to/prompt_library.json') }}"
                       value="{{ field_value }}"
                       data-custom-input="{{ field_id }}"
                       {% if field.disabled %}disabled{% endif %}>
            </div>
            <div class="form-text mt-2">
                Selecting a saved library fills this path automatically. Custom paths let you point at JSON files managed outside SimpleTuner.
            </div>
        </div>
        <script>
        (function() {
            function getTrainerStore() {
                return (window.Alpine && typeof window.Alpine.store === 'function')
                    ? window.Alpine.store('trainer')
                    : null;
            }

            function ensureSelectorModule() {
                if (window.promptLibrarySelector) {
                    return window.promptLibrarySelector;
                }

                const state = {
                    libraries: Array.isArray(window.__promptLibraries) ? window.__promptLibraries.slice() : [],
                    fields: new Map(),
                };

                const cleanupFields = () => {
                    state.fields.forEach((field, key) => {
                        if (!field.root || !field.root.isConnected) {
                            state.fields.delete(key);
                        }
                    });
                };

                const normalizePath = (value) => {
                    if (!value) {
                        return '';
                    }
                    return String(value).replace(/\\/g, '/').replace(/^\.\/+/, '');
                };

                const escapeHtml = (value) => {
                    if (value == null) {
                        return '';
                    }
                    return String(value).replace(/[&<>"']/g, (char) => ({
                        '&': '&amp;',
                        '<': '&lt;',
                        '>': '&gt;',
                        '"': '&quot;',
                        "'": '&#39;',
                    }[char] || char));
                };

                const getActiveEnvironment = () => {
                    const store = getTrainerStore();
                    return store && typeof store.activeEnvironment === 'string'
                        ? store.activeEnvironment.trim()
                        : '';
                };

                const dispatchValidation = (input) => {
                    if (!input) {
                        return;
                    }
                    input.dispatchEvent(new Event('input', { bubbles: true }));
                    input.dispatchEvent(new Event('change', { bubbles: true }));
                };

                const sortLibraries = () => {
                    const env = normalizePath(getActiveEnvironment());
                    const prefix = env ? `${env}/` : '';
                    const libs = state.libraries.slice();
                    libs.sort((a, b) => {
                        const priority = (entry) => {
                            const rel = normalizePath(entry?.relative_path || '');
                            return prefix && rel.startsWith(prefix) ? 1 : 0;
                        };
                        const diff = priority(b) - priority(a);
                        if (diff !== 0) {
                            return diff;
                        }
                        const labelFor = (entry) => (entry?.display_name || entry?.filename || '').toLowerCase();
                        return labelFor(a).localeCompare(labelFor(b));
                    });
                    return libs;
                };

                const formatLabel = (field, value) => {
                    const label = field.label;
                    if (!label) {
                        return;
                    }
                    const libs = state.libraries || [];
                    const match = libs.find((entry) => entry.relative_path === value || entry.absolute_path === value);
                    if (match) {
                        const env = getActiveEnvironment();
                        const relPath = match.relative_path || '';
                        const prefix = env ? `${env}/` : '';
                        const isEnvMatch = Boolean(prefix && relPath.startsWith(prefix));
                        const nameText = escapeHtml(match.display_name || match.filename || '');
                        const pathText = escapeHtml(relPath);
                        label.innerHTML = `
                            <span class="prompt-library-toggle-name">
                                ${nameText}
                                ${isEnvMatch ? '<span class="badge bg-primary-subtle text-primary-emphasis ms-2">Current env</span>' : ''}
                            </span>
                            <span class="prompt-library-toggle-path">${pathText}</span>
                        `;
                    } else if (value) {
                        const customText = escapeHtml(value);
                        label.innerHTML = `
                            <span class="prompt-library-toggle-name">Custom path</span>
                            <span class="prompt-library-toggle-path">${customText}</span>
                        `;
                    } else {
                        label.innerHTML = '<span class="text-muted">Select prompt library</span>';
                    }
                };

                const setHiddenValue = (field, value, source) => {
                    if (!field.hiddenInput) {
                        return;
                    }
                    const sanitized = value || '';
                    const changed = field.hiddenInput.value !== sanitized;
                    field.hiddenInput.value = sanitized;
                    if (field.customInput && source !== 'custom') {
                        field.customInput.value = sanitized;
                    }
                    formatLabel(field, sanitized);
                    if (changed) {
                        dispatchValidation(field.hiddenInput);
                    }
                    if (field.customContainer && source !== 'custom' && !field.customContainer.classList.contains('d-none')) {
                        field.customContainer.classList.add('d-none');
                        if (field.customToggle) {
                            field.customToggle.textContent = 'Use custom path';
                        }
                    }
                    if (field.customContainer && !sanitized && !field.customContainer.classList.contains('d-none')) {
                        field.customContainer.classList.add('d-none');
                        if (field.customToggle) {
                            field.customToggle.textContent = 'Use custom path';
                        }
                    }
                };

                const handleOptionSelect = (field, lib) => {
                    const nextValue = (lib?.absolute_path || lib?.relative_path || '').trim();
                    setHiddenValue(field, nextValue, 'dropdown');
                    if (field.dropdownInstance && typeof field.dropdownInstance.hide === 'function') {
                        field.dropdownInstance.hide();
                    }
                };

                const renderEmptyState = (menu) => {
                    const message = document.createElement('div');
                    message.className = 'dropdown-item text-muted small';
                    message.textContent = 'No prompt libraries found. Use the editor to create one.';
                    message.tabIndex = -1;
                    message.setAttribute('role', 'presentation');
                    menu.appendChild(message);
                };

                const renderOption = (field, lib) => {
                    const option = document.createElement('button');
                    option.type = 'button';
                    option.className = 'dropdown-item prompt-library-option';
                    option.dataset.value = lib.relative_path || '';
                    option.dataset.absolutePath = lib.absolute_path || '';
                    option.dataset.relativePath = lib.relative_path || '';
                    const env = normalizePath(getActiveEnvironment());
                    const prefix = env ? `${env}/` : '';
                    const isEnvMatch = Boolean(prefix && normalizePath(lib.relative_path || '').startsWith(prefix));
                    const name = document.createElement('span');
                    name.className = 'prompt-library-option-name';
                    name.textContent = lib.display_name || lib.filename || 'prompt library';
                    const path = document.createElement('span');
                    path.className = 'prompt-library-option-path';
                    path.textContent = lib.relative_path || lib.filename || '';
                    if (isEnvMatch) {
                        const badge = document.createElement('span');
                        badge.className = 'badge bg-primary-subtle text-primary-emphasis ms-2';
                        badge.textContent = 'Current env';
                        name.appendChild(badge);
                    }
                    option.appendChild(name);
                    option.appendChild(path);
                    const hiddenValue = field.hiddenInput ? field.hiddenInput.value : '';
                    if (hiddenValue && hiddenValue === (lib.absolute_path || lib.relative_path || '')) {
                        option.classList.add('active');
                    }
                    option.addEventListener('click', () => handleOptionSelect(field, lib));
                    return option;
                };

                const renderClearOption = (field) => {
                    const clearBtn = document.createElement('button');
                    clearBtn.type = 'button';
                    clearBtn.className = 'dropdown-item text-start';
                    clearBtn.textContent = 'Clear selection';
                    clearBtn.addEventListener('click', () => handleOptionSelect(field, { relative_path: '' }));
                    return clearBtn;
                };

                const populateMenu = (field) => {
                    if (!field.menu) {
                        return;
                    }
                    field.menu.innerHTML = '';
                    field.menu.appendChild(renderClearOption(field));
                    const libs = sortLibraries();
                    if (!libs.length) {
                        renderEmptyState(field.menu);
                        return;
                    }
                    libs.forEach((lib) => {
                        field.menu.appendChild(renderOption(field, lib));
                    });
                };

                const toggleCustomVisibility = (field, force) => {
                    if (!field.customContainer || !field.customToggle) {
                        return;
                    }
                    const nextState = typeof force === 'boolean'
                        ? force
                        : field.customContainer.classList.contains('d-none');
                    field.customContainer.classList.toggle('d-none', !nextState);
                    field.customToggle.textContent = nextState ? 'Hide custom path' : 'Use custom path';
                    if (nextState && field.customInput) {
                        field.customInput.value = field.hiddenInput?.value || '';
                        field.customInput.focus();
                        field.customInput.select();
                    }
                };

                const registerField = (root) => {
                    if (!root || root.dataset.promptLibraryInitialized === 'true') {
                        return;
                    }
                    root.dataset.promptLibraryInitialized = 'true';
                    const fieldId = root.dataset.promptLibraryField;
                    const hiddenInput = root.querySelector('input[type="hidden"]');
                    const label = root.querySelector('.prompt-library-toggle-label');
                    const menu = root.querySelector('.prompt-library-menu');
                    const toggle = root.querySelector('.prompt-library-toggle');
                    const customToggle = root.querySelector(`[data-custom-toggle="${fieldId}"]`);
                    const customContainer = root.querySelector(`[data-custom-container="${fieldId}"]`);
                    const customInput = customContainer ? customContainer.querySelector('input') : null;
                    const field = {
                        fieldId,
                        root,
                        hiddenInput,
                        label,
                        menu,
                        toggle,
                        customToggle,
                        customContainer,
                        customInput,
                        dropdownInstance: null,
                    };
                    if (toggle && window.bootstrap && window.bootstrap.Dropdown) {
                        field.dropdownInstance = window.bootstrap.Dropdown.getOrCreateInstance(toggle);
                    }
                    if (hiddenInput) {
                        hiddenInput.addEventListener('change', () => formatLabel(field, hiddenInput.value || ''));
                        hiddenInput.addEventListener('input', () => formatLabel(field, hiddenInput.value || ''));
                    }
                    if (toggle) {
                        toggle.addEventListener('click', () => populateMenu(field));
                    }
                    if (customInput) {
                        customInput.addEventListener('input', (event) => {
                            setHiddenValue(field, event.target.value || '', 'custom');
                        });
                    }
                    if (customToggle) {
                        customToggle.addEventListener('click', (event) => {
                            event.preventDefault();
                            toggleCustomVisibility(field);
                        });
                    }

                    const initialValue = hiddenInput ? hiddenInput.value : '';
                    const libs = state.libraries || [];
                    const match = libs.find((entry) => entry.relative_path === initialValue || entry.absolute_path === initialValue);
                    if (initialValue && !match) {
                        toggleCustomVisibility(field, true);
                    }
                    formatLabel(field, initialValue);
                    populateMenu(field);
                    if (fieldId && state.fields.has(fieldId)) {
                        state.fields.delete(fieldId);
                    }
                    state.fields.set(fieldId, field);
                };

                const init = (scope) => {
                    const target = scope || document;
                    cleanupFields();
                    target.querySelectorAll('[data-prompt-library-field]').forEach((root) => registerField(root));
                };

                const updateLibraries = (libs) => {
                    state.libraries = Array.isArray(libs) ? libs.slice() : [];
                    state.fields.forEach((field) => populateMenu(field));
                    state.fields.forEach((field) => formatLabel(field, field.hiddenInput?.value || ''));
                };

                window.addEventListener('promptLibrarySaved', (event) => {
                    const libs = event?.detail?.libraries;
                    if (Array.isArray(libs)) {
                        window.__promptLibraries = libs.slice();
                        updateLibraries(libs);
                    }
                });

                window.addEventListener('environment-changed', () => {
                    state.fields.forEach((field) => {
                        populateMenu(field);
                        formatLabel(field, field.hiddenInput?.value || '');
                    });
                });

                window.addEventListener('promptLibrariesRefreshed', (event) => {
                    const libs = event?.detail?.libraries;
                    if (Array.isArray(libs)) {
                        window.__promptLibraries = libs.slice();
                        updateLibraries(libs);
                    }
                });

                document.addEventListener('htmx:load', (event) => {
                    init(event?.detail?.elt || event.target);
                });

                document.addEventListener('htmx:afterSwap', () => init(document));

                return {
                    init,
                    updateLibraries,
                };
            }

            const selectorModule = ensureSelectorModule();
            selectorModule.init(document);
            if (Array.isArray(window.__promptLibraries)) {
                selectorModule.updateLibraries(window.__promptLibraries);
            }
        })();
        </script>
    {% elif custom_component == 'merge_environment_toggle' %}
        <div class="merge-env-toggle" x-data="mergeEnvironmentPopover('{{ 'true' if field_value else 'false' }}')">
            <input type="hidden" name="{{ field_name }}" x-model="mergeEnabledString">

            <div class="d-flex align-items-start gap-2">
                <div class="form-check form-switch mb-0">
                    <input type="checkbox"
                           class="form-check-input"
                           id="{{ field_id }}"
                           aria-labelledby="{{ field_id }}__switch_label"
                           :checked="mergeEnabled"
                           @change="mergeEnabled = $event.target.checked">
                    <span class="form-check-label" id="{{ field_id }}__switch_label">
                        {{ field.checkbox_label|default(field.label) }}
                    </span>
                </div>
                <div class="position-relative" @mouseenter="open = true" @mouseleave="open = false">
                    <button type="button"
                            class="btn btn-link btn-sm p-0 text-info help-icon"
                            @focus="open = true"
                            @blur="open = false"
                            @click.prevent="open = !open"
                            title="Show environment defaults"
                            aria-label="Show environment defaults">
                        ℹ️
                    </button>
                    <div class="merge-env-popover" x-cloak x-show="open" @mouseenter="open = true" @mouseleave="open = false" @keydown.escape.window="open = false">
                        <div class="merge-env-popover__content">
                            <template x-if="hasDefaults">
                                <pre x-text="defaultsJson"></pre>
                            </template>
                            <template x-if="!hasDefaults">
                                <span class="text-muted">No active environment configuration loaded.</span>
                            </template>
                        </div>
                    </div>
                </div>
            </div>

            {% if field.description and custom_component != 'prompt_library_path' %}
            <p class="form-text mt-2">{{ field.description }}</p>
            {% endif %}
        </div>

        <script>
        if (!window.__mergeEnvPopoverStyles) {
            window.__mergeEnvPopoverStyles = true;
            const style = document.createElement('style');
            style.textContent = `
            .merge-env-toggle { position: relative; }
            .merge-env-popover {
                position: absolute;
                top: 0;
                right: -12px;
                transform: translateY(100%);
                background-color: rgba(17, 24, 39, 0.95);
                border: 1px solid rgba(148, 163, 184, 0.25);
                box-shadow: 0 10px 30px rgba(15, 23, 42, 0.35);
                border-radius: 0.5rem;
                padding: 0.75rem;
                min-width: 320px;
                max-width: 420px;
                z-index: 1080;
            }
            .merge-env-popover__content {
                max-height: 280px;
                overflow-y: auto;
                font-family: var(--bs-font-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace);
                font-size: 0.8rem;
                color: #e2e8f0;
                white-space: pre;
            }
            .merge-env-popover__content pre {
                margin: 0;
                white-space: pre-wrap;
                word-break: break-word;
            }
            `;
            document.head.appendChild(style);
        }

        if (!window.mergeEnvironmentPopover) {
            window.mergeEnvironmentPopover = function(initialValue) {
                const initial = typeof initialValue === 'string'
                    ? initialValue.toLowerCase() !== 'false'
                    : Boolean(initialValue);
                return {
                    open: false,
                    mergeEnabled: initial,
                    init() {
                        try {
                            const stored = localStorage.getItem('simpletuner.mergeEnvironmentConfig');
                            if (stored === 'true' || stored === 'false') {
                                this.mergeEnabled = stored === 'true';
                            }
                        } catch (err) {
                            console.debug('mergeEnvironmentPopover storage unavailable', err);
                        }

                        if (Alpine.store('trainer')) {
                            Alpine.store('trainer').mergeEnvironmentDefaults = this.mergeEnabled;
                        }

                        this.$watch('mergeEnabled', (value) => {
                            try {
                                localStorage.setItem('simpletuner.mergeEnvironmentConfig', value ? 'true' : 'false');
                            } catch (err) {
                                console.debug('mergeEnvironmentPopover storage unavailable', err);
                            }
                            if (Alpine.store('trainer')) {
                                Alpine.store('trainer').mergeEnvironmentDefaults = value;
                            }
                        });
                    },
                    get mergeEnabledString() {
                        return this.mergeEnabled ? 'true' : 'false';
                    },
                    set mergeEnabledString(value) {
                        this.mergeEnabled = String(value).toLowerCase() !== 'false';
                    },
                    get hasDefaults() {
                        const store = Alpine.store('trainer');
                        const config = store ? store.activeEnvironmentConfig : null;
                        return config && Object.keys(config).length > 0;
                    },
                    get defaultsJson() {
                        try {
                            const store = Alpine.store('trainer');
                            const config = store ? store.activeEnvironmentConfig : null;
                            if (!config || Object.keys(config).length === 0) {
                                return 'No environment configuration loaded.';
                            }
                            return JSON.stringify(config, null, 2);
                        } catch (err) {
                            return 'Unable to render environment configuration.';
                        }
                    }
                };
            };
        }
        </script>

    {% elif field_type == 'checkbox' %}
        <div class="form-check form-switch">
            <input type="checkbox"
                   class="form-check-input"
                   id="{{ field_id }}"
                   name="{{ field_name }}"
                   value="true"
                   aria-labelledby="{{ field_id }}__title {{ field_id }}__switch_label"
                   {% if field_value %}checked{% endif %}
                   {% if field.disabled %}disabled{% endif %}
                   data-debounce="300"
                   hx-post="/api/validate/{{ field_id }}"
                   hx-trigger="change"
                   hx-target="#field-feedback-{{ field_id }}"
                   hx-swap="innerHTML"
                   hx-on::after-request="window.handleFieldValidation(event, this)"
                   data-feedback-id="field-feedback-{{ field_id }}">
            <span class="form-check-label" id="{{ field_id }}__switch_label">
                {{ field.checkbox_label|default('Enable') }}
            </span>
        </div>

    {% elif field_type == 'select' %}
        <select class="form-select"
                id="{{ field_id }}"
                name="{{ field_name }}"
                data-initial-value="{{ field_value }}"
                {% if field.disabled %}disabled{% endif %}
                data-debounce="300"
                hx-post="/api/validate/{{ field_id }}"
                hx-trigger="change"
                hx-target="#field-feedback-{{ field_id }}"
                hx-swap="innerHTML"
                hx-on::after-request="window.handleFieldValidation(event, this)"
                data-feedback-id="field-feedback-{{ field_id }}">
            {% if not field.required %}
            <option value="">-- Select --</option>
            {% endif %}
            {% for option in field.options %}
                {% if option is mapping %}
                    <option value="{{ option.value }}"
                            {% if option.value == field_value %}selected{% endif %}>
                        {{ option.label }}
                    </option>
                {% else %}
                    <option value="{{ option }}"
                            {% if option == field_value %}selected{% endif %}>
                        {{ option }}
                    </option>
                {% endif %}
            {% endfor %}
        </select>

    {% elif field_type == 'multi_select' %}
        <select class="form-select"
                id="{{ field_id }}"
                name="{{ field_name }}"
                multiple
                {% if field.disabled %}disabled{% endif %}
                data-debounce="300"
                hx-post="/api/validate/{{ field_id }}"
                hx-trigger="change"
                hx-target="#field-feedback-{{ field_id }}"
                hx-swap="innerHTML"
                hx-on::after-request="window.handleFieldValidation(event, this)"
                data-feedback-id="field-feedback-{{ field_id }}">
            {% for option in field.options %}
                {% if option is mapping %}
                    <option value="{{ option.value }}"
                            {% if option.value in field_value %}selected{% endif %}>
                        {{ option.label }}
                    </option>
                {% else %}
                    <option value="{{ option }}"
                            {% if option in field_value %}selected{% endif %}>
                        {{ option }}
                    </option>
                {% endif %}
            {% endfor %}
        </select>

    {% elif field_type == 'textarea' %}
        <textarea class="form-control"
                  id="{{ field_id }}"
                  name="{{ field_name }}"
                  rows="{{ field.rows|default(3) }}"
                  {% if field.placeholder %}placeholder="{{ field.placeholder }}"{% endif %}
                  {% if field.disabled %}disabled{% endif %}
                  data-debounce="500"
                  hx-post="/api/validate/{{ field_id }}"
                  hx-trigger="change"
                  hx-target="#field-feedback-{{ field_id }}"
                  hx-swap="innerHTML"
                  hx-on::after-request="window.handleFieldValidation(event, this)"
                  data-feedback-id="field-feedback-{{ field_id }}">{{ field_value }}</textarea>

    {% elif field_type == 'number' %}
        <input type="number"
               class="form-control"
               id="{{ field_id }}"
               name="{{ field_name }}"
               value="{{ field_value }}"
               {% if field.min is defined %}min="{{ field.min }}"{% endif %}
               {% if field.max is defined %}max="{{ field.max }}"{% endif %}
               {% if field.step is defined %}step="{{ field.step }}"{% endif %}
               {% if field.placeholder %}placeholder="{{ field.placeholder }}"{% endif %}
               {% if field.disabled %}disabled{% endif %}
               {% if field.required %}required{% endif %}
               data-debounce="500"
               hx-post="/api/validate/{{ field_id }}"
               hx-trigger="change"
               hx-target="#field-feedback-{{ field_id }}"
               hx-swap="innerHTML"
               hx-on::after-request="window.handleFieldValidation(event, this)"
               data-feedback-id="field-feedback-{{ field_id }}">

    {% elif field_type == 'file' %}
        <input type="file"
               class="form-control"
               id="{{ field_id }}"
               name="{{ field_name }}"
               {% if field.accept %}accept="{{ field.accept }}"{% endif %}
               {% if field.disabled %}disabled{% endif %}
               {% if field.required %}required{% endif %}
               hx-post="/api/validate/{{ field_id }}"
               hx-trigger="change"
               hx-target="#field-feedback-{{ field_id }}"
               hx-swap="innerHTML"
               hx-on::after-request="window.handleFieldValidation(event, this)"
               data-feedback-id="field-feedback-{{ field_id }}"
               hx-encoding="multipart/form-data">

    {% elif field_type == 'path' %}
        <div class="input-group">
            <input type="text"
                   class="form-control"
                   id="{{ field_id }}"
                   name="{{ field_name }}"
                   value="{{ field_value }}"
                   {% if field.placeholder %}placeholder="{{ field.placeholder }}"{% endif %}
                   {% if field.disabled %}disabled{% endif %}
                   {% if field.required %}required{% endif %}
                   data-debounce="500"
                   hx-post="/api/validate/{{ field_id }}"
                   hx-trigger="change"
                   hx-target="#field-feedback-{{ field_id }}"
                   hx-swap="innerHTML"
                   hx-on::after-request="window.handleFieldValidation(event, this)"
                   data-feedback-id="field-feedback-{{ field_id }}">
            <button class="btn btn-outline-secondary"
                    type="button"
                    hx-get="/api/browse/{{ field.browse_type|default('file') }}"
                    hx-target="#{{ field_id }}"
                    hx-swap="value"
                    {% if field.disabled %}disabled{% endif %}>
                <i class="fas fa-folder-open"></i>
            </button>
        </div>

    {% else %}
        <!-- Default text input -->
        <input type="text"
               class="form-control"
               id="{{ field_id }}"
               name="{{ field_name }}"
               value="{{ field_value }}"
               {% if field.placeholder %}placeholder="{{ field.placeholder }}"{% endif %}
               {% if field.disabled %}disabled{% endif %}
               {% if field.required %}required{% endif %}
               data-debounce="500"
               hx-post="/api/validate/{{ field_id }}"
               hx-trigger="change"
               hx-target="#field-feedback-{{ field_id }}"
               hx-swap="innerHTML"
               hx-on::after-request="window.handleFieldValidation(event, this)"
               data-feedback-id="field-feedback-{{ field_id }}">
    {% endif %}

    <!-- Help Text -->
    {% if field.description and field_type != 'checkbox' %}
    <div class="form-text">{{ field.description }}</div>
    {% endif %}

    <!-- HTMX Feedback Area -->
    <div id="field-feedback-{{ field_id }}" class="invalid-feedback" style="display: none;" data-validation-swap="true"></div>

    <!-- Loading indicator for this field -->
    <div class="field-loading htmx-indicator">
        <span class="spinner-border spinner-border-sm text-primary" role="status"></span>
    </div>
</div>

<style>
/* Field-specific loading indicator */
.field-loading {
    position: absolute;
    right: 10px;
    top: 38px;
    opacity: 0;
    transition: opacity 0.3s ease;
}

.htmx-request .field-loading {
    opacity: 1;
}

/* Path input group styling */
.input-group .btn-outline-secondary {
    border-color: rgba(255, 255, 255, 0.1);
}

.input-group .btn-outline-secondary:hover {
    background-color: rgba(255, 255, 255, 0.05);
    border-color: rgba(255, 255, 255, 0.2);
}

/* Multi-select styling */
select[multiple] {
    min-height: 100px;
}

/* Dataset dropdown styling */
.dataset-dropdown .dataset-toggle {
    background-color: rgba(15, 23, 42, 0.65);
    color: #e2e8f0;
    border: 1px solid rgba(148, 163, 184, 0.4);
    display: flex;
    align-items: center;
    padding-right: 2.5rem;
    position: relative;
    text-align: left;
    font-family: var(--bs-font-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace);
    font-size: 0.9rem;
}

.dataset-dropdown .dataset-toggle::after {
    position: absolute;
    right: 1rem;
    top: 50%;
    transform: translateY(-50%);
}

.dataset-dropdown .dataset-toggle:hover,
.dataset-dropdown .dataset-toggle:focus {
    background-color: rgba(30, 41, 59, 0.85);
    border-color: rgba(148, 163, 184, 0.65);
    color: #f8fafc;
    box-shadow: 0 0 12px rgba(56, 189, 248, 0.25);
}

.dataset-dropdown .dataset-toggle-label {
    display: flex;
    justify-content: space-between;
    align-items: center;
    width: 100%;
    flex: 1;
    min-width: 0;
}

.dataset-dropdown .dataset-env {
    font-weight: 600;
    flex: 0 0 auto;
    white-space: nowrap;
}

.dataset-dropdown .dataset-path {
    flex: 1 1 auto;
    text-align: right;
    font-family: var(--bs-font-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    min-width: 0;
}

.dataset-dropdown .dataset-dropdown-menu {
    max-height: 280px;
    overflow-y: auto;
    background-color: rgba(15, 23, 42, 0.95);
    border: 1px solid rgba(56, 189, 248, 0.25);
    box-shadow: 0 18px 40px rgba(8, 47, 73, 0.45);
    backdrop-filter: blur(6px);
}

.dataset-dropdown .dataset-option {
    gap: 0.5rem;
    color: #e2e8f0;
}

.dataset-dropdown .dataset-option:hover,
.dataset-dropdown .dataset-option:focus,
.dataset-dropdown .dataset-option.active,
.dataset-dropdown .dataset-option:active {
    background-color: rgba(56, 189, 248, 0.25);
    color: #f8fafc;
    border-left: 2px solid rgba(125, 211, 252, 0.6);
}

.dataset-dropdown .dataset-option .dataset-path {
    color: rgba(148, 163, 184, 0.85);
}

.dataset-dropdown .dataset-option:hover .dataset-path,
.dataset-dropdown .dataset-option:focus .dataset-path,
.dataset-dropdown .dataset-option.active .dataset-path {
    color: rgba(203, 213, 225, 0.9);
}

/* Prompt library dropdown styling */
.prompt-library-selector .prompt-library-toggle {
    background-color: rgba(15, 23, 42, 0.65);
    color: #e2e8f0;
    border: 1px solid rgba(148, 163, 184, 0.4);
    display: flex;
    align-items: center;
    justify-content: flex-start;
    text-align: left;
    padding-right: 2.5rem;
    position: relative;
}

.prompt-library-selector .prompt-library-toggle::after {
    position: absolute;
    right: 1rem;
    top: 50%;
    transform: translateY(-50%);
}

.prompt-library-selector .prompt-library-toggle:hover,
.prompt-library-selector .prompt-library-toggle:focus {
    background-color: rgba(30, 41, 59, 0.85);
    border-color: rgba(148, 163, 184, 0.65);
    color: #f8fafc;
}

.prompt-library-toggle-label {
    display: flex;
    flex-direction: column;
    width: 100%;
    min-width: 0;
    gap: 0.15rem;
}

.prompt-library-toggle-name {
    font-weight: 600;
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
}

.prompt-library-toggle-path {
    font-family: var(--bs-font-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace);
    font-size: 0.85rem;
    color: rgba(148, 163, 184, 0.85);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.prompt-library-dropdown .prompt-library-menu {
    max-height: 280px;
    overflow-y: auto;
    background-color: rgba(15, 23, 42, 0.95);
    border: 1px solid rgba(56, 189, 248, 0.25);
    box-shadow: 0 18px 40px rgba(8, 47, 73, 0.45);
    min-width: 100%;
}

.prompt-library-option {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 0.15rem;
    color: #e2e8f0;
}

.prompt-library-option-name {
    font-weight: 600;
}

.prompt-library-option-path {
    font-size: 0.85rem;
    font-family: var(--bs-font-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace);
    color: rgba(148, 163, 184, 0.85);
    word-break: break-all;
}

.prompt-library-selector .prompt-library-custom-toggle {
    color: rgba(125, 211, 252, 0.9);
}

.prompt-library-selector .prompt-library-custom-toggle:hover {
    color: #bae6fd;
}

.prompt-library-custom input {
    font-family: var(--bs-font-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace);
}

/* File input styling */
input[type="file"].form-control {
    padding: 0.375rem 0.75rem;
}

input[type="file"].form-control::file-selector-button {
    padding: 0.375rem 0.75rem;
    margin-right: 0.75rem;
    background-color: rgba(255, 255, 255, 0.05);
    border: 1px solid rgba(255, 255, 255, 0.1);
    color: #f8f9fa;
}

input[type="file"].form-control::file-selector-button:hover {
    background-color: rgba(255, 255, 255, 0.1);
}
</style>

<script>
window.handleFieldValidation = window.handleFieldValidation || function(event, element) {
    if (!event.detail || !event.detail.xhr) {
        return;
    }

    const responseText = (event.detail.xhr.responseText || '').trim();
    const feedbackId = element.getAttribute('data-feedback-id');
    const feedbackEl = feedbackId ? document.getElementById(feedbackId) : null;

    if (responseText.length > 0) {
        element.classList.add('field-invalid');
        element.classList.remove('field-valid');
        if (feedbackEl) {
            feedbackEl.classList.add('text-danger');
            feedbackEl.classList.remove('text-success');
            feedbackEl.style.display = 'block';
        }
    } else {
        element.classList.remove('field-invalid');
        element.classList.add('field-valid');
        if (feedbackEl) {
            feedbackEl.classList.remove('text-danger');
            feedbackEl.classList.add('text-success');
            feedbackEl.style.display = 'none';
        }
    }

    if (window.Alpine && Alpine.store('trainer')) {
        const trainerStore = Alpine.store('trainer');
        if (typeof trainerStore.markFormDirty === 'function') {
            trainerStore.markFormDirty();
        } else {
            trainerStore.formDirty = true;
            trainerStore._skipNextClean = true;
        }
    }
};
</script>
